/*
 * Copyright 2025-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package glz.hawk.poc.gen;

import com.github.javafaker.Faker;
import glz.hawk.poc.data.AuthorPo;
import org.jeasy.random.EasyRandom;
import org.jeasy.random.EasyRandomParameters;
import org.jeasy.random.FieldPredicates;
import org.jeasy.random.api.Randomizer;
import org.jeasy.random.randomizers.range.BigDecimalRangeRandomizer;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.time.*;
import java.util.Locale;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Predicate;

/**
 * This class is responsible for
 *
 * @author Zhang Peng
 */
public class AuthorGenerator {

    public static void main(String[] args) {
        Faker faker = faker();
        EasyRandom easyRandom = easyRandom();
        AuthorPo authorPo = easyRandom.nextObject(AuthorPo.class);
        System.out.println(authorPo.getAuthorName());
    }

    private static EasyRandom easyRandom() {
        EasyRandomParameters parameters = new EasyRandomParameters();
        EasyRandomParameters innerEasyRandomParameters = easyRandomParameters();
        EasyRandom innerEasyRandom = new EasyRandom(innerEasyRandomParameters);
        parameters.randomize(AuthorPo.class, () -> {
            AuthorPo authorPo = innerEasyRandom.nextObject(AuthorPo.class);
            authorPo.setUpdateUserId(authorPo.getCreateUserId());
            return authorPo;
        });
        return new EasyRandom(parameters);
    }

    private static EasyRandomParameters easyRandomParameters() {
        Faker faker = faker();
        EasyRandomParameters parameters = new EasyRandomParameters();
        // 设置字符串长度范围
        parameters.stringLengthRange(5, 20);
        // 限制日期范围
        parameters.dateRange(LocalDate.now().minusYears(20), LocalDate.now());
        // 设置字符集
        parameters.charset(StandardCharsets.UTF_8);
        // 设置数字范围（如价格 10-100 元）
        parameters.randomize(BigDecimal.class, new BigDecimalRangeRandomizer(0.01, 100.00));
        // 设置集合大小范围
        parameters.collectionSizeRange(2, 5);
        // 排除某些字段
        parameters.excludeField(FieldPredicates.named("deleteDateTime").and(FieldPredicates.inClass(AuthorPo.class)));
        parameters.excludeField(FieldPredicates.named("deleteUserId").and(FieldPredicates.inClass(AuthorPo.class)));

        // 对特定字段应用随机器
        Predicate<Field> createUserIdField = FieldPredicates.named("createUserId").and(FieldPredicates.inClass(AuthorPo.class));
        parameters.randomize(createUserIdField, () -> faker.random().nextInt(10000, 99999).toString());
        //  Predicate<Field> authorIdField = FieldPredicates.named("authorId").and(FieldPredicates.inClass(AuthorPo.class));
        //  parameters.randomize(authorIdField, () -> idGenerator.next());
        Predicate<Field> authorNameField = FieldPredicates.named("authorName").and(FieldPredicates.inClass(AuthorPo.class));
        parameters.randomize(authorNameField, faker.name()::fullName);

        Predicate<Field> createDateTimeField = FieldPredicates.named("createDateTime").and(FieldPredicates.inClass(AuthorPo.class));
        parameters.randomize(createDateTimeField, new LocalDateTimeRangeRandomizer(LocalDateTime.now().minusYears(150),LocalDateTime.now(), ZoneOffset.UTC));

        //        为接口/抽象类指定具体实现（如果需要）
        //// 如果某字段类型是接口或抽象类，需要告诉 EasyRandom 可用的具体类型
        //        params.scanClasspathForConcreteTypes(true); // 自动扫描（可能成本较高）
        //// 或者在某些版本中使用 registerConcreteType(Map<Class<?>, Class<?>>) 等（根据版本 API）

        return parameters;
    }

    public static Faker faker() {
        return new Faker(Locale.CHINA);
    }


    public static class LocalDateTimeRangeRandomizer implements Randomizer<LocalDateTime> {
        private long minEpochMilli;
        private long maxEpochMilli;
        private ZoneId zone;

        /**
         * 时区：LocalDateTime 本身不包含时区信息，转换为 epoch milli 时需提供 ZoneId。
         * 通常用 ZoneId.systemDefault() 或 ZoneOffset.UTC，根据你的需求选择。
         *
         * @param min
         * @param max
         * @param zone
         */
        public LocalDateTimeRangeRandomizer(LocalDateTime min, LocalDateTime max, ZoneId zone) {
            this.zone = zone;
            this.minEpochMilli = min.atZone(zone).toInstant().toEpochMilli();
            this.maxEpochMilli = max.atZone(zone).toInstant().toEpochMilli();
            if (minEpochMilli > maxEpochMilli) {
                throw new IllegalArgumentException("min must be <= max");
            }
        }

        @Override
        public LocalDateTime getRandomValue() {
            long randMillis = ThreadLocalRandom.current().nextLong(minEpochMilli, maxEpochMilli + 1);
            return LocalDateTime.ofInstant(Instant.ofEpochMilli(randMillis), zone);
        }
    }

    public static class LocalDateRangeRandomizer implements Randomizer<LocalDate> {
        private long minDay;
        private long maxDay;

        public LocalDateRangeRandomizer(LocalDate min, LocalDate max) {
            this.minDay = min.toEpochDay();
            this.maxDay = max.toEpochDay();
        }

        @Override
        public LocalDate getRandomValue() {
            long randomDay = ThreadLocalRandom.current().nextLong(minDay, maxDay + 1);
            return LocalDate.ofEpochDay(randomDay);
        }
    }


}
